/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package nl.uva.weevil.core.topology;

import java.util.HashMap;
import java.util.HashSet;

/**
 *
 * @author reggie
 */
public class Topology<N,P> {    
    public static int PORT_DIRECTION_IN = 11;
    public static int PORT_DIRECTION_OUT = 12;
    private HashSet /*key:K -> node:N*/ centralNodes = new HashSet();
    private HashSet /*key:K -> node:N*/ rootNodes = new HashSet();
    private HashSet /*key:K -> node:N*/ leafNodes = new HashSet();
    private HashMap /*source:P -> destinations:HashSet*/ connections = new HashMap();    
    private HashMap /*node:N -> ports:HashSet*/ inputPorts = new HashMap();
    private HashMap /*node:N -> ports:HashSet*/ outputPorts = new HashMap();
    private HashMap /*port:N -> node:N*/ invertedPortIndex = new HashMap();   
    
    public void addNode(N node){           
        this.rootNodes.add(node);
        this.leafNodes.add(node);
        HashSet hsi = new HashSet();
        HashSet hso = new HashSet();
        inputPorts.put(node, hsi);
        outputPorts.put(node, hso);        
    }
    
    public void addPort2Node(P port, N node, int portDirection){
        if(portDirection == Topology.PORT_DIRECTION_IN){
            HashSet hs = (HashSet)inputPorts.get(node);
            hs.add(port);
            this.rootNodes.remove(node);
            if(hasOutputPorts(node) == true)
                this.centralNodes.add(node);
        }
        if(portDirection == Topology.PORT_DIRECTION_OUT){
            HashSet hs = (HashSet)outputPorts.get(node);
            hs.add(port);
            this.leafNodes.remove(node);
            HashSet hsp = new HashSet();
            this.connections.put(port, hsp);
            if(hasInputPorts(node) == true)
                this.centralNodes.add(node);
        }
        this.invertedPortIndex.put(port, node);
    }
    
    public void connectPorts(P source, P destination){
        if((this.invertedPortIndex.containsKey(source) == true) &&
                (this.invertedPortIndex.containsKey(destination) == true) ){           
            HashSet hs = (HashSet)this.connections.get(source);
            hs.add(destination);
        }
    } 
    
    private boolean hasInputPorts(N node){
        HashSet hs = (HashSet)this.inputPorts.get(node);
        if(hs.size() > 0)
            return true;
        
        return false;
    }
    
    private boolean hasOutputPorts(N node){
        HashSet hs = (HashSet)this.outputPorts.get(node);
        if(hs.size() > 0)
            return true;
        
        return false;
    }
    
    @Override
    public String toString(){
        String ret = "";
        
        return ret;
    }
    
}
